Skip to content

开发一个telegram IP地址归属地查询机器人

Published:

最近研究了一下telegram的机器人,用go开发了一个IP地址归属地查询机器人.

创建一个新Bot 获取token

在Telegram中搜索并关注BotFather,发送/newbot命令创建一个机器人,获取返回的token.

IP地址查询逻辑

import (
	"strings"
	"github.com/lionsoul2014/ip2region/binding/golang/xdb"
	"github.com/samber/do/v2"
	"github.com/samber/lo"
)

type IP2RegionService struct {
	searcher *xdb.Searcher
}

func (s *IP2RegionService) Search(ip string) (string, error) {
	res, err := s.searcher.SearchByStr(ip)
	if err != nil {
		return "", err
	}

	arr := lo.Filter(strings.Split(res, "|"), func(item string, _ int) bool {
		return item != "0"
	})

	return strings.Join(lo.Union(arr), " "), nil
}

func NewIP2RegionService(i do.Injector) (*IP2RegionService, error) {
	searcher, err := xdb.NewWithFileOnly("./ip2region.xdb")
	if err != nil {
		return nil, err
	}
	return &IP2RegionService{
		searcher: searcher,
	}, nil
}

telegram机器人逻辑

import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"regexp"
	"strings"

	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
	"github.com/samber/do/v2"
)

type TelegramBotService struct {
	bot              *tgbotapi.BotAPI
	ip2RegionService *IP2RegionService
}

func (s *TelegramBotService) handleIP2Region(update tgbotapi.Update, ipStr string) {
	log.Printf("get IP string: %s\n", ipStr)

	ipStr = strings.TrimSpace(ipStr)

	ips := strings.Split(ipStr, ",")

	result := ""
	for index, ip := range ips {
		if index != 0 {
			result += "\n"
		}
		region, err := s.ip2RegionService.Search(strings.TrimSpace(ip))
		if err != nil {
			result += fmt.Sprintf("%s: %s", ip, err.Error())
		} else {
			result += fmt.Sprintf("%s: %s", ip, region)
		}
	}

	msg := tgbotapi.NewMessage(update.Message.Chat.ID, result)
	msg.ReplyToMessageID = update.Message.MessageID
	s.bot.Send(msg)
}

func (s *TelegramBotService) Start() {
	re := regexp.MustCompile("/(search|echo) (.+)")

	u := tgbotapi.NewUpdate(0)
	u.Timeout = 60
	updates := s.bot.GetUpdatesChan(u)
	log.Println("bot start")
	for update := range updates {
		if update.Message != nil {
			log.Printf("recive message, UserName:%s ,Text:%s\n", update.Message.From.UserName, update.Message.Text)

			txt := update.Message.Text
			matches := re.FindStringSubmatch(txt)

			if len(matches) < 3 {
				continue
			}

			switch matches[1] {
			case "echo":
				s.bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, matches[2]))
			case "search":
				s.handleIP2Region(update, matches[2])
			}

		}
	}
}

func NewTelegramBotService(i do.Injector) (*TelegramBotService, error) {
	config := do.MustInvoke[*ConfigService](i)
	if config.UseProxy {
		proxyUrl, err := url.Parse(config.ProxyUrl)
		if err != nil {
			return nil, err
		}
		bot, err := tgbotapi.NewBotAPIWithClient(config.Token,
			tgbotapi.APIEndpoint,
			&http.Client{
				Transport: &http.Transport{
					Proxy: http.ProxyURL(proxyUrl),
				},
			})
		if err != nil {
			return nil, err
		}
		return &TelegramBotService{
			bot:              bot,
			ip2RegionService: do.MustInvoke[*IP2RegionService](i),
		}, nil
	} else {
		bot, err := tgbotapi.NewBotAPI(config.Token)
		if err != nil {
			return nil, err
		}
		return &TelegramBotService{
			bot:              bot,
			ip2RegionService: do.MustInvoke[*IP2RegionService](i),
		}, nil
	}
}

提供两个命令:
echo: 将你发送的内容直接返回, eg: /echo Hello
search: IP地址归属地查询, eg: /search 1.1.1.1,2.2.2.2,3.3.3.3

代码地址: https://github.com/moys3389/ip2region-tg-bot